﻿using System.Collections.Generic;
using System.Linq;
using Cms.Application.Admin.Views;
using Cms.Data;
using Cms.Domain;
using Cms.Domain.RepositoryInterfaces;
using Cms.Utilities;

namespace Cms.Application.Admin.Presenters
{
    public class LoginPresenter : BasePresenter
    {
        private readonly ILoginView _view;

        public LoginPresenter(ILoginView view)
            : this(view, new RepositoryFactory())
        {
        }

        public LoginPresenter(ILoginView view, IRepositoryFactory repositoryFactory)
            : base(view, repositoryFactory)
        {
            _view = view;
        }
        
        public void Initialize()
        {
            // First, check for autologin credentials
            if (!string.IsNullOrEmpty(_view.AutoLoginEncryptedCredentials))
            {
                ExtractCredentialsAndSetUsernameAndPassword(_view.AutoLoginEncryptedCredentials);
                Authenticate();
                return;
            }
            // Second, if the user has chosen to save her credentials in a cookie, set the username and password textboxes
            if (_view.SavedEncryptedCredentials == null)
                return;
            ExtractCredentialsAndSetUsernameAndPassword(_view.SavedEncryptedCredentials);
            _view.RememberCredentials = true;
        }

        private void ExtractCredentialsAndSetUsernameAndPassword(string encryptedCredentials)
        {
            string decryptedCredentials = Cipher.Decrypt(encryptedCredentials);
            if (decryptedCredentials == null)
                return;
            string[] credentials = decryptedCredentials.Split((char)9);
            _view.Username = credentials[0];
            _view.Password = credentials[1];
        }

        public void Authenticate()
        {
            Administrator admin = AdministratorRepository.GetAdministrator(_view.Username, _view.Password);
            if (admin == null)
            {
                AddValidationError(1, GetText(_view, "WrongCredentialsError"));
                _view.DisplayErrorAndPromptForNewLogin();
                return;
            }
            if (admin.AvailableSites.Count > 0)
            {
                if (admin.DefaultSite == null || !admin.AvailableSites.Contains(admin.DefaultSite))
                    admin.DefaultSite = admin.AvailableSites[0];
                admin.CurrentSite = admin.DefaultSite;
                if (admin.CurrentSite.Domain.ToLower() != _view.RequestedDomain.ToLower())
                {
                    Site requestedSite = FindRequestedSite(admin.AvailableSites);
                    if (requestedSite != null)
                        admin.CurrentSite = requestedSite;
                }
                admin.CurrentSiteLocale = admin.CurrentSite.DefaultLocale;
                AdministratorRepository.SaveAdministrator(admin);
                _view.Login(admin);
            }
            else if (admin.HasPermission.ConfigureFirstSite)
                _view.ConfigureFirstSite(admin);
            else
            {
                AddValidationError(2, GetText(_view, "NoAvailableSiteError"));
                _view.DisplayErrorAndPromptForNewLogin();
            }
        }

        private Site FindRequestedSite(IList<Site> availableSites)
        {
            IList<Site> sites = SiteRepository.GetSites();
            foreach (Site site in sites.Where(site => availableSites.Contains(site)))
            {
                if (site.Domain.ToLower() == _view.RequestedDomain.ToLower())
                    return site;
                if (site.AliasDomains.Any(siteAlias => siteAlias.ToLower() == _view.RequestedDomain.ToLower()))
                    return site;
                if (
                    site.Locales.Any(
                        locale =>
                        locale.AliasDomain != null && locale.AliasDomain.ToLower() == _view.RequestedDomain.ToLower()))
                    return site;
            }
            return null;
        }
    }
}